/***************************************************************************//**
* \file CapSense_Adc.c
* \version 3.0
*
* \brief
*   This file provides implementation for the ADC module of the CapSense 
*   component.
*
* \see CapSense P4 v3.0 Datasheet
*
*//*****************************************************************************
* Copyright (2016), Cypress Semiconductor Corporation.
********************************************************************************
* This software is owned by Cypress Semiconductor Corporation (Cypress) and is
* protected by and subject to worldwide patent protection (United States and
* foreign), United States copyright laws and international treaty provisions.
* Cypress hereby grants to licensee a personal, non-exclusive, non-transferable
* license to copy, use, modify, create derivative works of, and compile the
* Cypress Source Code and derivative works for the sole purpose of creating
* custom software in support of licensee product to be used only in conjunction
* with a Cypress integrated circuit as specified in the applicable agreement.
* Any reproduction, modification, translation, compilation, or representation of
* this software except as specified above is prohibited without the express
* written permission of Cypress.
*
* Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH
* REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* Cypress reserves the right to make changes without further notice to the
* materials described herein. Cypress does not assume any liability arising out
* of the application or use of any product or circuit described herein. Cypress
* does not authorize its products for use as critical components in life-support
* systems where a malfunction or failure may reasonably be expected to result in
* significant injury to the user. The inclusion of Cypress' product in a life-
* support systems application implies that the manufacturer assumes all risk of
* such use and in doing so indemnifies Cypress against all charges. Use may be
* limited by and subject to the applicable Cypress software license agreement.
*******************************************************************************/
#include <cytypes.h>
#include "CyLib.h"

#include "CapSense_Structure.h"
#include "CapSense_Configuration.h"
#include "CapSense_Adc.h"
#if ((CapSense_ENABLE == CapSense_CSD_EN) || (CapSense_ENABLE == CapSense_CSX_EN))
    #include "CapSense_Sensing.h"
#endif  /* ((CapSense_ENABLE == CapSense_CSD_EN) 
         || (CapSense_ENABLE == CapSense_CSX_EN)) */

#if (CapSense_ADC_EN)

static uint8 CapSense_initVar;
uint16 CapSense_AdcVref_mV = CapSense_ADC_VREF_MV;
/*******************************************************************************
* Module local function declarations
*******************************************************************************/
/**
* \if SECTION_ADC_INTERNAL
* \addtogroup group_adc_internal
* \{
*/

static void CapSense_SetNonDedicatedAdcChannel(uint8 chId, uint32 state);

/** \}
* \endif */

/*******************************************************************************
* Local definition
*******************************************************************************/
#define CapSense_AdcINIT_DONE   (1u)
#define CapSense_AdcINIT_NEEDED (0u)
#define CapSense_AdcCAL_WATCHDOG_CYCLES_NUM   (0x0000FFFFLu)

/*******************************************************************************
* Function Name: CapSense_SetNonDedicatedAdcChannel
****************************************************************************//**
*
* \brief
*   Sets the non dedicated channel to the given state.
*
* \details
*   Connects/disconnects the pin and the analog muxbus B. Sets the drive mode
*   of the pin as well.
*
* \param chId  The ID of the non dedicated channel to be set.
* \param state The state in which the channel is to be put:
*         - (0) CapSense_AdcCHAN_DISCONNECT
*         - (1) CapSense_AdcCHAN_CONNECT
*
*******************************************************************************/
static void CapSense_SetNonDedicatedAdcChannel(uint8 chId, uint32 state)
{
    CapSense_FLASH_IO_STRUCT const *ptr2adcIO;
    uint32 newRegisterValue;
    uint8  interruptState;
    uint32 pinHSIOMShift;
    uint32 pinModeShift;
    uint32 tmpVal;

    ptr2adcIO = &CapSense_adcIoList[chId];
    pinHSIOMShift = (uint32)ptr2adcIO->hsiomShift;
    pinModeShift = (uint32)ptr2adcIO->shift;
    
    /* Clear port connections. */
    tmpVal = CY_GET_REG32(ptr2adcIO->hsiomPtr);
    tmpVal &= ~(CapSense_AdcHSIOM_PRTSEL_MASK << pinHSIOMShift);
    
    interruptState = CyEnterCriticalSection();

    switch (state)
    {
    case CapSense_AdcCHAN_CONNECT:
        
        /* Connect AMuxBusB to the selected port. */
        CY_SET_REG32(ptr2adcIO->hsiomPtr, (tmpVal \
            | (CapSense_AdcHSIOM_PRTSEL_AMUXBUSB << pinHSIOMShift)));
    
        /* Update port configuration register (drive mode) to HiZ output, buffered input */
        newRegisterValue = CY_GET_REG32(ptr2adcIO->pcPtr);
        newRegisterValue &= ~(CapSense_AdcGPIO_PC_MASK << pinModeShift);
        newRegisterValue |= (CapSense_AdcGPIO_PC_INPUT << pinModeShift);
        CY_SET_REG32(ptr2adcIO->pcPtr, newRegisterValue);
    
        /* Cmod and Ctank are not typical GPIO, require CSD setting. */
        if (0u != ((uint32)(ptr2adcIO->hsiomPtr) & CapSense_AdcSW_CMOD_PORT_MASK))
        {
            if (CapSense_AdcSW_CTANK_PINSHIFT == pinModeShift)
            {
                CY_SET_REG32(CapSense_AdcSW_DSI_SEL_PTR, \
                    CapSense_AdcSW_DSI_CTANK);  
            }
            else if (CapSense_AdcSW_CMOD_PINSHIFT == pinModeShift)
            {
                CY_SET_REG32(CapSense_AdcSW_DSI_SEL_PTR, \
                    CapSense_AdcSW_DSI_CMOD);  
            }
            else { /* No action */ }
        }
        break;
        
    /* Disconnection is a safe default state. Fall-through is intentional. */
    case CapSense_AdcCHAN_DISCONNECT:
    default:
        /* tmpVal contains cleared hsiom state. */
        CY_SET_REG32(ptr2adcIO->hsiomPtr, tmpVal);
    
        /* Update port configuration register (drive mode) to HiZ input/output by clearing PC*/
        newRegisterValue = CY_GET_REG32(ptr2adcIO->pcPtr);
        newRegisterValue &= ~(CapSense_AdcGPIO_PC_MASK << pinModeShift);
        CY_SET_REG32(ptr2adcIO->pcPtr, newRegisterValue);
        
        /* Cmod and Ctank are not typical GPIO, require CSD setting. */
        if (0u != ((uint32)(ptr2adcIO->hsiomPtr) & CapSense_AdcSW_CMOD_PORT_MASK))
        {
            if ((CapSense_AdcSW_CTANK_PINSHIFT == pinModeShift) ||
                (CapSense_AdcSW_CMOD_PINSHIFT == pinModeShift ))
            {
                CY_SET_REG32(CapSense_AdcSW_DSI_SEL_PTR, 0u);  
            }
        }
        break;
    }

    CyExitCriticalSection(interruptState);
    
    /* Set logic 0 to port data register */
    tmpVal = CY_GET_REG32(ptr2adcIO->drPtr);
    tmpVal &= (uint32)~(uint32)((uint32)1u << ptr2adcIO->drShift);
    CY_SET_REG32(ptr2adcIO->drPtr, tmpVal);
}


/*******************************************************************************
* Function Name: CapSense_SetAdcChannel
****************************************************************************//**
*
* \brief
*   Sets the given channel to the given state.
*
* \details
*   Connects/disconnects the pin and the analog muxbus B.  Sets the drive mode
*   of the pin as well.
*
* \param chId  The ID of the channel to be set.
* \param state The state in which the channel is to be put:
*         - (0) CapSense_AdcCHAN_DISCONNECT
*         - (1) CapSense_AdcCHAN_CONNECT
*
*******************************************************************************/
void CapSense_SetAdcChannel(uint8 chId, uint32 state)
{
    #if (0u != CapSense_ADC_AMUXB_INPUT_EN)
        if(CapSense_ADC_SELECT_AMUXB_CH != chId)
        {
            CapSense_SetNonDedicatedAdcChannel(chId, state);
        }
    #else
        CapSense_SetNonDedicatedAdcChannel(chId, state);   
    #endif /* (0u != CapSense_ADC_AMUXB_INPUT_EN) */
}


/*******************************************************************************
* Function Name: CapSense_ConfigAdcResources
****************************************************************************//**
*
* \brief
*   Configures the CSD block to be used as an ADC.
*
* \details
*   Configures the IDACB, internal switches, REFGEN, and HSCOMP.
*
*******************************************************************************/
void CapSense_ConfigAdcResources(void)
{   
    uint32 totalClkDiv;
    /* Configure the IDAC */
    CY_SET_REG32(CapSense_AdcCONFIG_PTR, CapSense_AdcCONFIG_DEFAULT );
    CY_SET_REG32(CapSense_AdcSENSE_PERIOD_PTR, \
        CapSense_AdcSENSE_SINGLEDIV);
    CY_SET_REG32(CapSense_AdcIDACB_PTR, \
     CapSense_AdcIDACB_CONFIG \
     | CapSense_dsRam.adcIdac);
    /* Autozero time needs to be scaled down by clock dividers.
       Autozero time should be 5us. SEQ_TIME_DEFAULT is the duration assuming clk_sns = clk_hf.
       Actually, clk_sns = clk_hf/(csd_peri_div * sense_div) */ 
    totalClkDiv = (CapSense_AdcSENSE_SINGLEDIV + 1UL) \
        * (((CY_GET_REG32(CapSense_ModClk__DIV_REGISTER)>>CapSense_AdcCLK16VAL_SHIFT)
        & CapSense_AdcCLK16_MASK) + 1UL);
    
    if(0u < (CapSense_AdcSEQ_TIME_BASE / totalClkDiv))
    {
        CY_SET_REG32(CapSense_AdcSEQ_TIME_PTR, \
                (CapSense_AdcSEQ_TIME_BASE / totalClkDiv) - 1u);
    }
    else
    {
        CY_SET_REG32(CapSense_AdcSEQ_TIME_PTR, 0u);        
    }
    CY_SET_REG32(CapSense_AdcIDACA_PTR, 0ul);
    CY_SET_REG32(CapSense_AdcCSDCMP_PTR, 0ul);
    CY_SET_REG32(CapSense_AdcSW_DSI_SEL_PTR, 0ul);
    
    CY_SET_REG32(CapSense_AdcSENSE_DUTY_PTR, 0ul);
    CY_SET_REG32(CapSense_AdcSEQ_INIT_CNT_PTR, 1ul);
    CY_SET_REG32(CapSense_AdcSEQ_NORM_CNT_PTR, 2ul);
    
    /* Configure the block-level routing */
    CY_SET_REG32(CapSense_AdcSW_HS_P_SEL_PTR, CapSense_AdcSW_HSP_DEFAULT);
    CY_SET_REG32(CapSense_AdcSW_HS_N_SEL_PTR, CapSense_AdcSW_HSN_DEFAULT);
    CY_SET_REG32(CapSense_AdcSW_SHIELD_SEL_PTR, \
        CapSense_AdcSW_SHIELD_DEFAULT);
    CY_SET_REG32(CapSense_AdcSW_BYP_SEL_PTR, CapSense_AdcSW_BYP_DEFAULT);
    CY_SET_REG32(CapSense_AdcSW_CMP_P_SEL_PTR, \
        CapSense_AdcSW_CMPP_DEFAULT);
    CY_SET_REG32(CapSense_AdcSW_CMP_N_SEL_PTR, \
        CapSense_AdcSW_CMPN_DEFAULT);
    CY_SET_REG32(CapSense_AdcSW_FW_MOD_SEL_PTR, \
        CapSense_AdcSW_FWMOD_DEFAULT);
    CY_SET_REG32(CapSense_AdcSW_FW_TANK_SEL_PTR, \
        CapSense_AdcSW_FWTANK_DEFAULT);

    /* Config RefGen.  The routing of the HS_N and AMUXBUF switches depend on RefGen. */
    #if (CapSense_AdcVDDA_MV < CapSense_AdcLVTHRESH)

        CY_SET_REG32(CapSense_AdcREFGEN_PTR, CapSense_AdcREFGEN_LV);
        CY_SET_REG32(CapSense_AdcSW_AMUXBUF_SEL_PTR, \
            CapSense_AdcSW_AMUBUF_LV);
        CY_SET_REG32(CapSense_AdcAMBUF_PTR, CapSense_AdcAMBUF_LV);
    #else
        CY_SET_REG32(CapSense_AdcREFGEN_PTR, CapSense_AdcREFGEN_NORM);
        CY_SET_REG32(CapSense_AdcSW_AMUXBUF_SEL_PTR, \
            CapSense_AdcSW_AMUBUF_NORM);
    #endif /* CapSense_AdcVDDA_MV < CapSense_AdcLVTHRESH */
    
    /* Configure HSCOMP */
    CY_SET_REG32(CapSense_AdcHSCMP_PTR, CapSense_AdcHSCMP_AZ_DEFAULT);
    
    /* Set the ISR vector */
    CapSense_ISR_StartEx(&CapSense_AdcIntrHandler);
    
    /* Component is initialized */
    CapSense_initVar = CapSense_AdcINIT_DONE;
}


/*******************************************************************************
* Function Name: CapSense_StartAdcFSM
****************************************************************************//**
*
* \brief
*   Starts the CSD state machine with correct parameters to initialize an ADC
*   conversion.
*
* \details
*   Starts the CSD state machine with correct parameters to initialize an ADC
*   conversion.
*
* \param measureMode The FSM mode:
*        - (0) CapSense_AdcMEASMODE_OFF    
*        - (1) CapSense_AdcMEASMODE_VREF   
*        - (2) CapSense_AdcMEASMODE_VREFBY2
*        - (3) CapSense_AdcMEASMODE_VIN    
*
*******************************************************************************/
void CapSense_StartAdcFSM(uint32 measureMode)
{
    uint32 totalClkDiv;
    uint32 tmpStartVal;
    /* Set the mode and aperture size. */
    totalClkDiv = (CapSense_AdcSENSE_SINGLEDIV + 1UL) \
        * (((CY_GET_REG32(CapSense_ModClk__DIV_REGISTER)>>CapSense_AdcCLK16VAL_SHIFT)
        & CapSense_AdcCLK16_MASK) + 1UL);
    
    CY_SET_REG32(CapSense_AdcADC_CTL_PTR, (measureMode | \
                 ((CapSense_AdcMEASURE_APERTURE_BASE / totalClkDiv ) - 1u)));
    
    if(CapSense_AdcMEASMODE_VREF == measureMode)
    {
        tmpStartVal = 
            CapSense_AdcFSMSETTING_AZSKIP_DEFAULT    |
            CapSense_AdcFSMSETTING_DSIIGNORE   |
            CapSense_AdcFSMSETTING_NOABORT     |
            CapSense_AdcFSMSETTING_SEQMODE     |
            CapSense_AdcFSMSETTING_START;
    }
    else if (CapSense_AdcMEASMODE_OFF == measureMode)
    {
        tmpStartVal = CapSense_AdcFSMSETTING_ABORT;
    }
    /* This setting is used for both MEASMODE_VREFBY2 and MEASMODE_VIN */
    else
    {
        tmpStartVal = \
            CapSense_AdcFSMSETTING_AZSKIP_DEFAULT    |
            CapSense_AdcFSMSETTING_DSIIGNORE   |
            CapSense_AdcFSMSETTING_NOABORT     |
            CapSense_AdcFSMSETTING_SEQMODE     |
            CapSense_AdcFSMSETTING_START;
    }
    /* Enable HSComp */
    CY_SET_REG32(CapSense_AdcSEQ_START_PTR, tmpStartVal);
}


/*******************************************************************************
* Function Name: CapSense_AdcCaptureResources
****************************************************************************//**
*
* \brief
*   Releases CSD resources from CapSense mode, and sets it into ADC mode.
*
* \details
*   Releases CSD resources from CapSense mode, and sets it into ADC mode.
*
* \return     The function returns cystatus of its operation.
*   - CYRET_LOCKED  - The CSD hardware is in-use by CapSense, and could not be released.
*   - CYRET_SUCCESS - Block is configured for ADC use.
*
*******************************************************************************/
cystatus CapSense_AdcCaptureResources(void)
{
    cystatus tmpStatus = CYRET_SUCCESS;

    #if ((CapSense_ENABLE == CapSense_CSD_EN) || (CapSense_ENABLE == CapSense_CSX_EN))
        tmpStatus = CapSense_SsReleaseResources();

        if (CapSense_AdcINIT_NEEDED == CapSense_initVar)
        {
            if(CYRET_SUCCESS == tmpStatus) 
            {
                CapSense_ConfigAdcResources();
            }
            else
            {
                tmpStatus = CYRET_LOCKED;
            }
        }
    #else
        if (CapSense_AdcINIT_NEEDED == CapSense_initVar)
        {
            CapSense_ConfigAdcResources();
        } 
    #endif

    return tmpStatus;
}


/*******************************************************************************
* Function Name: CapSense_AdcReleaseResources
****************************************************************************//**
*
* \brief
*   Releases CSD resources from ADC mode.
*
* \details
*   Releases CSD resources from ADC mode.
*
* \return     The function returns cystatus of its operation.
*   CYRET_SUCCESS   Block resources no longer in use.
*
*******************************************************************************/
cystatus CapSense_AdcReleaseResources(void)
{
    if (CapSense_AdcINIT_DONE == CapSense_initVar)
    {
        /* If the FSM is running, shut it down. */
        if(CapSense_AdcSTATUS_IDLE != (CapSense_dsRam.adcStatus \
            & CapSense_AdcSTATUS_FSM_MASK))
        {
            CapSense_StartAdcFSM(CapSense_AdcMEASMODE_OFF);
            CapSense_SetAdcChannel((CapSense_dsRam.adcStatus \
                & (uint8)(CapSense_AdcSTATUS_LASTCHAN_MASK)),
                                            CapSense_AdcCHAN_DISCONNECT);
            CapSense_dsRam.adcStatus = CapSense_AdcSTATUS_IDLE;
        }
        
        /* Disable the subblocks. */
        CY_SET_REG32(CapSense_AdcIDACB_PTR, 0x0UL);
        CY_SET_REG32(CapSense_AdcREFGEN_PTR, 0x0UL);
        CY_SET_REG32(CapSense_AdcAMBUF_PTR,  0x0UL);
        CY_SET_REG32(CapSense_AdcHSCMP_PTR,  0x0UL);
        
        /* Reset the block-level routing */
        CY_SET_REG32(CapSense_AdcSW_HS_P_SEL_PTR,    0x0UL);
        CY_SET_REG32(CapSense_AdcSW_HS_N_SEL_PTR,    0x0UL);
        CY_SET_REG32(CapSense_AdcSW_SHIELD_SEL_PTR,  0x0UL);
        CY_SET_REG32(CapSense_AdcSW_BYP_SEL_PTR,     0x0UL);
        CY_SET_REG32(CapSense_AdcSW_CMP_P_SEL_PTR,   0x0UL);
        CY_SET_REG32(CapSense_AdcSW_CMP_N_SEL_PTR,   0x0UL);
        CY_SET_REG32(CapSense_AdcSW_FW_MOD_SEL_PTR,  0x0UL);
        CY_SET_REG32(CapSense_AdcSW_FW_TANK_SEL_PTR, 0x0UL);
        
         /* Disconnect all ADC channels */
        CapSense_ClearAdcChannels();
        
        CapSense_initVar = CapSense_AdcINIT_NEEDED;
    }
    
    return CYRET_SUCCESS;
}


/*******************************************************************************
* Function Name: CapSense_AdcStartConvert
****************************************************************************//**
*
* \brief
*  Initializes an analog-to-digital conversion on the selected channel.
*
* \details
*  Initializes an analog-to-digital conversion on the selected channel.
*
* \param chId 
*  The ID of the channel to be converted. 
*
* \return 
*  The function returns cystatus of its operation.
*    - CYRET_LOCKED - The CSD hardware is in-use by CapSense. No conversion started.
*    - CYRET_BAD_PARAM - The chId was out of bounds. No conversion started.
*    - CYRET_STARTED - The ADC is already converting. No conversion started.
*    - CYRET_SUCCESS - A conversion has started. No conversion started.
*
*******************************************************************************/
cystatus CapSense_AdcStartConvert(uint8 chId)
{
    uint32 tmpStatus;
    
    tmpStatus = CapSense_AdcCaptureResources();

    if (CYRET_SUCCESS == tmpStatus)
    {
        if(chId >= CapSense_ADC_TOTAL_CHANNELS)
        {
            tmpStatus = CYRET_BAD_PARAM;
        }
        if (CYRET_SUCCESS == tmpStatus)
        {
            if(CapSense_AdcSTATUS_IDLE != (CapSense_dsRam.adcStatus & CapSense_AdcSTATUS_FSM_MASK))
            {
                tmpStatus = CYRET_STARTED;
            }
            
            if(CYRET_SUCCESS == tmpStatus)
            {
                /* Set Component Status */
                CapSense_dsRam.adcStatus = (CapSense_AdcSTATUS_CONVERTING | chId);
                
                /* Connect desired input */
                CapSense_SetAdcChannel(chId, CapSense_AdcCHAN_CONNECT);
                    
                /* Set interrupt request */
                CY_SET_REG32(CapSense_AdcINTR_MASK_PTR, CapSense_AdcINTERRUPT_SET);
                CapSense_StartAdcFSM(CapSense_AdcMEASMODE_VIN);
            }
        }
    }
    return tmpStatus;
}


/*******************************************************************************
* Function Name: CapSense_AdcIsBusy
****************************************************************************//**
*
* \brief
*   The function returns the status of ADC's operation.
*
* \details
*   The function returns the status of ADC's operation.
*
* \return     
*  The function returns status of the ADC's operation.
*    - CapSense_AdcSTATUS_IDLE - The ADC is not in use.
*    - CapSense_AdcSTATUS_CONVERTING - A conversion is 
*      in progress.
*    - CapSense_AdcSTATUS_CALIBPH1 - The ADC is in the 
*      first phase (of 2) of calibration.
*    - CapSense_AdcSTATUS_CALIBPH2 - The ADC is in the 
*      second phase (of 2) of calibration.
*    - CapSense_AdcSTATUS_OVERFLOW - The most recent 
*      measurement caused an overflow.
*
*******************************************************************************/
uint8 CapSense_AdcIsBusy(void)
{
    uint8 tmpStatus;
    if (0u != (CapSense_AdcADC_RES_REG & CapSense_AdcADC_RES_OVERFLOW_MASK))
    {
        tmpStatus = CapSense_AdcSTATUS_OVERFLOW;
    }
    else
    {
        tmpStatus = (uint8)((*(volatile uint8 *)&CapSense_dsRam.adcStatus) & CapSense_AdcSTATUS_FSM_MASK);
    }
    return tmpStatus;
}


/*******************************************************************************
* Function Name: CapSense_AdcReadResult_mVolts
****************************************************************************//**
*
* \brief
*  The blocking function that starts a conversion and waits for the result; 
*  returning it. 
*
* \details
*  The blocking function that starts a conversion and waits for the result; 
*  returning it.
*
* \param chId  
*  The ID of the channel to be measured 
*
* \return
*  The function returns voltage in millivolts or
*  CapSense_AdcVALUE_BADCHANID if chId is invalid.
*
*******************************************************************************/
uint16 CapSense_AdcReadResult_mVolts(uint8 chId)
{
    uint16 tmpValue;
    (void) CapSense_AdcStartConvert(chId);
    while(CapSense_AdcIsBusy() != CapSense_AdcSTATUS_IDLE)
    {
    }
    tmpValue = CapSense_AdcGetResult_mVolts(chId);
    return tmpValue;
}


/*******************************************************************************
* Function Name: CapSense_AdcGetResult_mVolts
****************************************************************************//**
*
* \brief
*  Returns the last valid result for the given channel.
*
* \details
*  Returns the last valid result for the given channel.
*
* \param chId  
*  The ID of the channel to be measured 
*
* \return     
*  The function returns voltage in mV or
*  CapSense_AdcVALUE_BADCHANID if chId is invalid.
*
*******************************************************************************/
uint16 CapSense_AdcGetResult_mVolts(uint8 chId)
{
    uint32 tmpRetVal = CapSense_AdcVALUE_BADCHANID;
    
    if(chId < CapSense_ADC_TOTAL_CHANNELS)
    {
        tmpRetVal = CapSense_dsRam.adcResult[chId];
    }
    return (uint16)tmpRetVal;
}


/*******************************************************************************
* Function Name: CapSense_AdcCalibrate
****************************************************************************//**
*
* \brief
*  Performs built-in calibration.
*
* \details
*  Performs built-in calibration.
*
* \return  
*  The function returns cystatus of its operation.
*    - CYRET_LOCKED    - The CSD hardware is in-use by CapSense, and could not be released.
*    - CYRET_SUCCESS   - The block is configured for ADC use.
*    - CYRET_STARTED   - Another ADC operation is in progress; this one was not completed.
*   
*******************************************************************************/
cystatus CapSense_AdcCalibrate(void)
{
    uint32 tmpStatus;
    uint32 watchdogAdcCounter;

    tmpStatus = CapSense_AdcCaptureResources();
    if(CapSense_AdcSTATUS_IDLE != (CapSense_dsRam.adcStatus \
        & CapSense_AdcSTATUS_FSM_MASK) )
    {
        tmpStatus = CYRET_STARTED;
    }
    
    if (CYRET_SUCCESS == tmpStatus)
    {
        uint32 totalClkDiv;
        uint8 tmpFlashByte0;
        uint8 tmpFlashByte1;
        uint32 tmpVrefCal;
        #if (0u != CYREG_SFLASH_CSDV2_CSD0_ADC_TRIM1)
            tmpFlashByte0 = CY_GET_REG8(CYREG_SFLASH_CSDV2_CSD0_ADC_TRIM1);
            tmpFlashByte1 = CY_GET_REG8(CYREG_SFLASH_CSDV2_CSD0_ADC_TRIM2);
            tmpVrefCal = (uint32)tmpFlashByte0 | (((uint32)tmpFlashByte1) << 8u);
            tmpVrefCal = (tmpVrefCal * (uint32)(CapSense_ADC_VREF_MV)) \
                         / (uint32)(CapSense_AdcVREFCALIB_BASE);
            CapSense_AdcVref_mV = (uint16)tmpVrefCal;
        #endif
        totalClkDiv = (CapSense_AdcSENSE_SINGLEDIV + 1UL) \
            * (((CY_GET_REG32(CapSense_ModClk__DIV_REGISTER)>>CapSense_AdcCLK16VAL_SHIFT)
            & CapSense_AdcCLK16_MASK) + 1UL);
        if(0u < (uint8)( CapSense_ADC_IDACVAL / totalClkDiv))
        {
            CapSense_dsRam.adcIdac = (uint8)( CapSense_ADC_IDACVAL / totalClkDiv);
        }
        else
        {
            CapSense_dsRam.adcIdac = 1u;
        }
        CY_SET_REG32(CapSense_AdcIDACB_PTR, \
                     CapSense_AdcIDACB_CONFIG \
                     | CapSense_dsRam.adcIdac);
        CapSense_dsRam.adcStatus = (CapSense_AdcSTATUS_CALIBPH1);
        CY_SET_REG32(CapSense_AdcINTR_MASK_PTR, CapSense_AdcINTERRUPT_SET);
        CapSense_StartAdcFSM(CapSense_AdcMEASMODE_VREF);
    }
    
    /* Initialize Watchdog Counter with time interval which is enough to ADC clibration is completed */
    watchdogAdcCounter = CapSense_AdcCAL_WATCHDOG_CYCLES_NUM;
    while (((*(volatile uint8 *)&CapSense_dsRam.adcStatus & CapSense_AdcSTATUS_FSM_MASK) \
            != 0u) &&  (0u != watchdogAdcCounter))
    {
        /* Wait until scan complete and decrement Watchdog Counter to prevent unending loop */
        watchdogAdcCounter--;
    }
    
    return tmpStatus;
}


/*******************************************************************************
* Function Name: CapSense_AdcInitialize
****************************************************************************//**
*
* \brief
*   Configures the hardware to ADC mode and begins a calibration.
*
* \details
*   Configures the hardware to ADC mode and begins a calibration.
*
*******************************************************************************/
void CapSense_AdcInitialize(void)
{
    CapSense_ConfigAdcResources();
    (void) CapSense_AdcCalibrate();
}


/*******************************************************************************
* Function Name: CapSense_AdcStop
****************************************************************************//**
*
* \brief
*   Disables the CSD sub-blocks that are in use while in the ADC mode, and frees 
*   the routing.
*
* \details
*   Disables the CSD sub-blocks that are in use while in the ADC mode, and frees 
*   the routing.
*
*******************************************************************************/
void CapSense_AdcStop(void)
{
    /* Add here function implementation */
    (void) CapSense_AdcReleaseResources();
    CapSense_initVar = CapSense_AdcINIT_NEEDED;
}


/*******************************************************************************
* Function Name: CapSense_AdcResume
****************************************************************************//**
*
* \brief
*   Resumes the ADC Component after a Stop call.
*
* \details
*   Resumes the ADC Component after a Stop call.
*
*******************************************************************************/
void CapSense_AdcResume(void)
{
    CapSense_AdcInitialize();
}


/*******************************************************************************
* Function Name: CapSense_ClearAdcChannels
****************************************************************************//**
*
* \brief
*  Resets all the ADC channels to disconnected state.
*
* \details
*   The function goes through all the ADC channels and disconnects the pin 
*   and the analog muxbus B.  Sets the drive mode of the pin as well.
* 
*******************************************************************************/
void CapSense_ClearAdcChannels(void)
{
    uint32 chId;

    for (chId = 0u; chId < CapSense_ADC_TOTAL_CHANNELS; chId++)
    {
        CapSense_SetAdcChannel((uint8)chId, CapSense_AdcCHAN_DISCONNECT);
    }   
}

#endif  /* #if CapSense_ADC_EN */  


/* [] END OF FILE */
